package com.yugao.fintech.draper.demos.controller;

import com.yugao.fintech.draper.auth.dto.UserInfoVO;
import com.yugao.fintech.draper.multicache.support.CacheMessage;
import com.yugao.fintech.draper.core.model.ResultVO;
import com.yugao.fintech.draper.oss.client.ftp.FtpFileStorage;
import com.yugao.fintech.draper.message.queue.client.RedisMQTemplate;
import com.yugao.fintech.draper.core.enums.ErrorCodes;
import com.yugao.fintech.draper.core.util.I18nUtil;
import com.yugao.fintech.draper.idempotent.annotation.Idempotent;
import com.yugao.fintech.draper.idempotent.keyresolver.impl.ExpressionIdempotentKeyResolver;
import com.yugao.fintech.draper.redisson.utils.RedissonUtils;
import com.yugao.fintech.draper.sequence.service.Sequence;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RateType;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/demo")
@RequiredArgsConstructor
@Tag(name = "测试")
public class DemoController {

    private final Sequence fxzSequence;

    private final Sequence cloudSequence;

    private final RedisMQTemplate redisMQTemplate;

    private final ObjectProvider<FtpFileStorage> ftpFileStorage;

    @GetMapping("/ftp")
    public ResultVO<String> ftp() {
        String res = ftpFileStorage.getIfAvailable().putObject("ftp文件上传测试".getBytes(), "/Users/fxz/oss/testFtp.txt");
        return ResultVO.success(res);
    }

    @Operation(summary = "xss过滤简易demo")
    @GetMapping("/xss")
    public ResultVO<String> xss(@RequestParam("value") String value) {
        return ResultVO.success(value);
    }

    @Operation(summary = "限流器")
    @GetMapping("/redisson/rateLimiter")
    public ResultVO<Long> rateLimiter() {
        return ResultVO.success(RedissonUtils.rateLimiter("demo.rateLimiter", RateType.OVERALL, 2, 20));
    }

    @Operation(summary = "向topic发布消息")
    @GetMapping("/pubsub/pub")
    public ResultVO<Void> pubTopic(@RequestParam("topic") String topic, @RequestParam("msg") String msg) {
        RedissonUtils.publish(topic, msg);
        return ResultVO.success();
    }

    @Operation(summary = "手动订阅频道")
    @GetMapping("/pubsub/sub")
    public ResultVO<Void> subTopic(@RequestParam("topic") String topic) {
        RedissonUtils.subscribe(topic, String.class, (channel, msg) -> log.info("接收到消息:{},{}", channel, msg));
        return ResultVO.success();
    }

    @Operation(summary = "清除缓存")
    @CacheEvict(value = "demo", key = "#id")
    @GetMapping("/cache/evict")
    public ResultVO<String> cacheEvict(Long id) {
        redisMQTemplate.send(new CacheMessage());
        return ResultVO.success(id.toString());
    }

    @Cacheable(value = "demo", key = "#id")
    @GetMapping("/cache/demo")
    public ResultVO<String> get(Long id) {
        return ResultVO.success(id.toString());
    }

    @SneakyThrows
    @GetMapping("/seqTestZdy")
    public ResultVO<String> seqTestZdy() {
        return ResultVO.success(fxzSequence.nextValue("fxz") + ":" + cloudSequence.nextValue("cloud"));
    }

    @GetMapping("/messageTest")
    public ResultVO<String> messageTest() {
        return ResultVO.error(I18nUtil.getMessage(ErrorCodes.SYS_TEST_MESSAGE_STR, "参数1", "参数2"));
    }

    @Idempotent(timeout = 10, message = "别发请求，等我执行完")
    @PostMapping("/idempotentObj")
    public ResultVO<Void> idempotentObj(@RequestBody UserInfoVO user) {
        log.info("方法执行");
        return ResultVO.success();
    }

    @Idempotent(timeout = 10, message = "别发请求，等我执行完", keyResolver = ExpressionIdempotentKeyResolver.class, key = "#str")
    @GetMapping("/idempotent")
    public ResultVO<Void> testIdempotent(String str) {
        log.info("方法执行");
        return ResultVO.success();
    }

    @Idempotent(timeout = 10, message = "别发请求，等我执行完", keyResolver = ExpressionIdempotentKeyResolver.class, key = "#str",
            delKey = true)
    @GetMapping("/idempotentDel")
    public ResultVO<Void> idempotentDel(String str) {
        log.info("方法执行且执行完自动删除key");
        return ResultVO.success();
    }
}
